好的！以下是一个完整的俄罗斯方块游戏代码，使用 Python 和 Pygame 库实现。你可以直接复制并运行它，体验游戏功能。

### 完整代码
```python
import pygame
import random
import sys

# 初始化 Pygame
pygame.init()

# 游戏常量
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
GAME_WIDTH, GAME_HEIGHT = 300, 600
GRID_WIDTH, GRID_HEIGHT = GAME_WIDTH // 30, GAME_HEIGHT // 30
BLOCK_SIZE = 30
SIDEBAR_WIDTH = SCREEN_WIDTH - GAME_WIDTH
FPS = 60
SCORE_FONT = pygame.font.SysFont("Arial", 24)
GAME_OVER_FONT = pygame.font.SysFont("Arial", 48)

# 颜色定义
BG_COLOR = (0, 0, 0)
GRID_COLOR = (50, 50, 50)
TEXT_COLOR = (255, 255, 255)
BLOCK_COLORS = [
    (0, 255, 255),  # I
    (0, 0, 255),    # J
    (255, 165, 0),  # L
    (255, 255, 0),  # O
    (0, 255, 0),    # S
    (128, 0, 128),  # T
    (255, 0, 0)     # Z
]

# 方块形状定义
SHAPES = {
    'I': [[1, 1, 1, 1]],
    'J': [[1, 0],
          [1, 0],
          [1, 1]],
    'L': [[0, 1],
          [0, 1],
          [1, 1]],
    'O': [[1, 1],
          [1, 1]],
    'S': [[0, 1, 1],
          [1, 1, 0]],
    'T': [[0, 1, 0],
          [1, 1, 1]],
    'Z': [[1, 1, 0],
          [0, 1, 1]]
}

# 游戏变量
game_grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
current_piece = None
next_piece = None
current_piece_pos = (0, 0)
score = 0
game_over = False
speed = 500  # 方块下落速度（毫秒）
last_fall_time = pygame.time.get_ticks()


def new_piece():
    """生成新的方块"""
    global current_piece, next_piece
    if next_piece is None:
        next_piece = random.choice(list(SHAPES.values()))
    current_piece = next_piece
    next_piece = random.choice(list(SHAPES.values()))
    return current_piece, 0, 0


def rotate_piece(piece):
    """旋转方块"""
    return [list(row) for row in zip(*piece[::-1])]


def check_collision(piece, offset):
    """检测方块是否碰撞"""
    x, y = offset
    for i, row in enumerate(piece):
        for j, cell in enumerate(row):
            if cell:
                try:
                    if game_grid[y + i][x + j] or x + j < 0 or y + i >= GRID_HEIGHT:
                        return True
                except IndexError:
                    return True
    return False


def lock_piece(piece, offset):
    """锁定方块到游戏网格"""
    x, y = offset
    for i, row in enumerate(piece):
        for j, cell in enumerate(row):
            if cell:
                game_grid[y + i][x + j] = BLOCK_COLORS.index(BLOCK_COLORS[current_piece]) + 1


def clear_lines():
    """清除满行并加分"""
    global score
    lines_cleared = 0
    for i, row in enumerate(game_grid):
        if all(row):
            del game_grid[i]
            game_grid.insert(0, [0] * GRID_WIDTH)
            lines_cleared += 1
    if lines_cleared == 1:
        score += 100
    elif lines_cleared == 2:
        score += 300
    elif lines_cleared == 3:
        score += 600
    elif lines_cleared == 4:
        score += 1000


def draw_game():
    """绘制游戏界面"""
    screen.fill(BG_COLOR)
    # 绘制游戏网格
    for y, row in enumerate(game_grid):
        for x, cell in enumerate(row):
            if cell:
                pygame.draw.rect(screen, BLOCK_COLORS[cell - 1], (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
            pygame.draw.rect(screen, GRID_COLOR, (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 1)
    # 绘制当前方块
    if current_piece:
        for i, row in enumerate(current_piece):
            for j, cell in enumerate(row):
                if cell:
                    pygame.draw.rect(screen, BLOCK_COLORS[current_piece_pos[2]], (j * BLOCK_SIZE + current_piece_pos[0] * BLOCK_SIZE, i * BLOCK_SIZE + current_piece_pos[1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
    # 绘制分数
    score_text = SCORE_FONT.render(f"Score: {score}", True, TEXT_COLOR)
    screen.blit(score_text, (GAME_WIDTH + 20, 20))
    # 绘制下一个方块
    next_text = SCORE_FONT.render("Next:", True, TEXT_COLOR)
    screen.blit(next_text, (GAME_WIDTH + 20, 60))
    for i, row in enumerate(next_piece):
        for j, cell in enumerate(row):
            if cell:
                pygame.draw.rect(screen, BLOCK_COLORS[current_piece_pos[2]], (j * BLOCK_SIZE + GAME_WIDTH + 20, i * BLOCK_SIZE + 100, BLOCK_SIZE, BLOCK_SIZE))


def game_over_screen():
    """游戏结束界面"""
    game_over_text = GAME_OVER_FONT.render("Game Over", True, TEXT_COLOR)
    score_text = SCORE_FONT.render(f"Score: {score}", True, TEXT_COLOR)
    restart_text = SCORE_FONT.render("Press R to Restart", True, TEXT_COLOR)
    screen.fill(BG_COLOR)
    screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT // 2 - game_over_text.get_height() - 50))
    screen.blit(score_text, (SCREEN_WIDTH // 2 - score_text.get_width() // 2, SCREEN_HEIGHT // 2))
    screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2, SCREEN_HEIGHT // 2 + 50))


# 初始化游戏
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Tetris")
clock = pygame.time.Clock()
current_piece, x, y = new_piece()
current_piece_pos = (x, y, BLOCK_COLORS.index(BLOCK_COLORS[current_piece]))

# 游戏主循环
running = True
while running:
    screen.fill(BG_COLOR)
    draw_game()

    if game_over:
        game_over_screen()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                game_grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
                score = 0
                game_over = False
                current_piece, x, y = new_piece()
                current_piece_pos = (x, y, BLOCK_COLORS.index(BLOCK_COLORS[current_piece]))
        pygame.display.update()
        continue

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                if not check_collision(current_piece, (x - 1, y)):
                    x -= 1
            if event.key == pygame.K_RIGHT:
                if not check_collision(current_piece, (x + 1, y)):
                    x += 1
            if event.key == pygame.K_DOWN:
                if not check_collision(current_piece, (x, y + 1)):
                    y += 1
            if event.key == pygame.K_UP:
                rotated_piece = rotate_piece(current_piece)
                if not check_collision(rotated_piece, (x, y)):
                    current_piece = rotated_piece
            if event.key == pygame.K_SPACE:
                while not check_collision(current_piece, (x, y + 1)):
                    y += 1

    current_time = pygame.time.get_ticks()
    if current_time - last_fall_time > speed:
        if not check_collision(current_piece, (x, y + 1)):
            y += 1
        else:
            lock_piece(current_piece, (x, y))
            clear_lines()
            current_piece, x, y = new_piece()
            current_piece_pos = (x, y, BLOCK_COLORS.index(BLOCK_COLORS[current_piece]))
            if check